﻿#region License Revision: 0 Last Revised: 6/18/2008 11:00 AM
/******************************************************************************
Copyright (c) Microsoft Corporation.  All rights reserved.


This file is licensed under the Microsoft Public License (Ms-PL). A copy of the Ms-PL should accompany this file. 
If it does not, you can obtain a copy from: 

http://www.microsoft.com/resources/sharedsource/licensingbasics/publiclicense.mspx
******************************************************************************/
#endregion // License
using System;
using System.Windows.Browser;
using System.Diagnostics;
using System.Collections.Generic;
using System.Globalization;
using System.Collections.ObjectModel;

namespace ScriptInterop
{
    public static class ScriptObjectUtility
    {

        private const string HelperScript =
        @"({
		createDelegate: function(f) {
		return function() { f.apply(null, arguments); };
		},
		enumerate: function(o) {
		var members = [];
		for (var m in o) {
			members.push(m);
		}
		return members;
		}
		})";

        private static ScriptObject s_helperObject;

        static ScriptObjectUtility()
        {
            s_helperObject = (ScriptObject)HtmlPage.Window.Eval(HelperScript);
        }

        /// <summary>
        /// Helper function to return the appropriate value based on desired return type
        /// </summary>
        /// <typeparam name="T">Type to return</typeparam>
        /// <param name="value">value passed in</param>
        /// <returns>value as a type 'T'</returns>
        static public T ConvertValue<T>(object value)
        {
            if (value == null)
            {
                return default(T);
            }

            ScriptObject objectValue = value as ScriptObject;
            if (objectValue != null)
            {
                return objectValue.ConvertTo<T>();
            }
            else
            {
                Type desiredPropertyType = typeof(T);
                return (T)Convert.ChangeType(value, desiredPropertyType, CultureInfo.InvariantCulture);
            }
        }

        public static object GetItem(this ScriptObject obj, int index)
        {
            return obj.GetProperty(index.ToString(CultureInfo.InvariantCulture));
        }

        public static T GetItem<T>(this ScriptObject obj, int index)
        {
            return obj.GetProperty<T>(index.ToString(CultureInfo.InvariantCulture));
        }

        public static T GetProperty<T>(this ScriptObject obj, string member)
        {
            object value = obj.GetProperty(member);
            if (value == null)
            {
                return default(T);
            }

            Type desiredPropertyType = typeof(T);
            ScriptObject objectValue = value as ScriptObject;
            if (objectValue != null)
            {
                return objectValue.ConvertTo<T>();
            }
            else
            {
                return (T)Convert.ChangeType(value, desiredPropertyType, CultureInfo.InvariantCulture);
            }
        }

        public static ScriptObject ToScriptFunction(this Delegate dele)
        {
            return (ScriptObject)s_helperObject.Invoke("createDelegate", dele);
        }

        public static IEnumerable<string> GetMembers(this ScriptObject obj)
        {
            ScriptObject members = (ScriptObject)s_helperObject.Invoke("enumerate", obj);
            int length = members.GetProperty<int>("length");
            for (int i = 0; i < length; i++)
            {
                yield return members.GetItem<string>(i);
            }
        }
    }
}
